package gang.org.springframework.framework.core.type.classreading;

import gang.org.springframework.framework.io.GangDefaultResourceLoader;
import gang.org.springframework.framework.io.GangResource;
import gang.org.springframework.framework.io.GangResourceLoader;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 * @author gang.chen
 * @description
 * @Date 2021/8/3 13:39
 */
public class GangCachingMetadataReaderFactory extends GangSimpleMetadataReaderFactory{

    public static final int DEFAULT_CACHE_LIMIT = 256;

    private Map<GangResource,GangMetadataReader> metadataReaderCache;

    public GangCachingMetadataReaderFactory() {
        super();
        setCacheLimit(DEFAULT_CACHE_LIMIT);
    }

    public GangCachingMetadataReaderFactory(GangResourceLoader resourceLoader){
        super(resourceLoader);
        if (resourceLoader instanceof GangDefaultResourceLoader) {

            this.metadataReaderCache = ((GangDefaultResourceLoader)resourceLoader).getResourceCache(GangMetadataReader.class);

        }else {
            //TODO
        }
    }

    @Override
    public GangMetadataReader getMetadataReader(GangResource resource) {
        if (this.metadataReaderCache instanceof ConcurrentMap) {

            GangMetadataReader metadataReader = this.metadataReaderCache.get(resource);

            if (metadataReader == null) {

                metadataReader = super.getMetadataReader(resource);

                this.metadataReaderCache.put(resource, metadataReader);
            }

            return metadataReader;
        }
        else if (false)
        {
            return null;
        }
        else
        {
            return super.getMetadataReader(resource);
        }
    }

    public void setCacheLimit(int cacheLimit){
        //TODO
        this.metadataReaderCache = new LocalResourceCache(cacheLimit);
    }


    private static class LocalResourceCache extends LinkedHashMap<GangResource,GangMetadataReader>{
        private volatile int cacheLimit;

        public LocalResourceCache(int cacheLimit){
            super(cacheLimit,0.75f,true);
            this.cacheLimit = cacheLimit;
        }
    }
}
